package com.ai.dmc.utils.string;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

/**
 * 
 * <p>Title: StringEncoding.java</p>
 * <p>Description: 字符串的转码，将字符串从一种编码格式转化为另一种编码格式,
 * 或某种编码格式和GBK的相互转换，Native和Ascii字符串的互相转化等</p>
 * <p>Copyright: Copyright (c) 2009</p>
 * <p>Company: 亚信科技（中国）有限公司</p>
 * @author chenhui2
 * @version 1.0
 *
 */
public class StringEncoding {
	
	
	/**
	 * 
	 * 两种编码格式转换,各种类型转换都适用，请传入相应的参数
	 * @param s				内容字符串
	 * @param oldCharName	原编码格式
	 * @param newCharName	目标编码格式
	 * @return
	 * String
	 *
	 */
	public static String convertCode(String s, String oldCharName, String newCharName) {
		if (StringUtil.isEmpty(s)) {
			return "";
		}
		try {
			return new String(s.getBytes(oldCharName), newCharName);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null; //TODO 是返回原字符串还是null？？？
		}

	}

	/**
	 * GBK编码转换为数据库编码
	 * @param s				待转换的字符串
	 * @param dbEncoding	目标编码格式
	 * @return
	 * String
	 *
	 */
	public static String convert2Db(String s, String dbEncoding) {
		if (StringUtil.isEmpty(s) || isGBK(dbEncoding)) {
			return s;
		}
		try {
			return new String(s.getBytes("GBK"), dbEncoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return "";
		}

	}

	/**
	 * 转换数据库编码为GBK编码
	 * @param s				待转换的字符串
	 * @param dbEncoding	数据库编码格式
	 * @return
	 * String		GBK编码的字符串
	 *
	 */
	public static String convert2GBK(String s, String dbEncoding) {
		if (StringUtil.isEmpty(s)) {
			return "";
		} else if (isGBK(dbEncoding)) {
			return s;
		}
		try {
			return new String(s.getBytes(dbEncoding), "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * 转换数据库编码为GBK编码
	 * @param obj			待转换的对象（处理时先转化为字符串）
	 * @param dbEncoding	数据库编码格式
	 * @return
	 * String				GBK编码的字符串
	 *
	 */
	public static String convert2GBK(Object obj,String dbEncoding) {
		if (null == obj) {
			return "";
		} else if (isGBK(dbEncoding)) {
			return StringUtil.obj2Str(obj);
		}
		try {
			return new String(StringUtil.obj2Str(obj).getBytes(dbEncoding), "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}

	}
	
    /**
     * 把字符串的编码从ISO-8859-1转换为GBK.
     * @param str 输入字符串.
     * @return 编码后的字符串.
     */
    public static String ISO2GBK(String str)
    {
        if(str == null)
        {
            return null;
        }

        try
        {
            byte[] b = str.getBytes("ISO-8859-1");
            str = new String(b,"GBK");

            return str;
        }

        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把字符串的编码从GBK转换为ISO-8859-1.
     * @param str 输入字符串.
     * @return 编码后的字符串.
     */
    public static String GBK2ISO(String str)
    {
        if(str == null)
        {
            return null;
        }

        try
        {
            byte[] b = str.getBytes("GBK");
            str = new String(b,"ISO-8859-1");

            return str;
        }

        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }
	
	/**
	 * 数据库是否为GBK编码 默认是，返回true
	 * @param dbEncoding	编码格式
	 * @return
	 * boolean
	 *
	 */
	public static boolean isGBK(String dbEncoding) {
		if (StringUtil.isEmpty(dbEncoding)
				|| dbEncoding.equalsIgnoreCase("null")
				|| dbEncoding.equalsIgnoreCase("gbk")
				|| dbEncoding.equalsIgnoreCase("gb2312")) {
			return true;
		}
		return false;
	}
	
	/**
	 * 
	 * Native to ascii string. It's same as execute native2ascii.exe.
	 * 
	 * @param str	native string
	 * @return
	 * String	ascii string
	 *
	 */
	public static String ascii2Native(String str) {
		StringBuffer buffer = new StringBuffer();

		try {
			ByteArrayOutputStream fos = new ByteArrayOutputStream(str.getBytes().length);
			Writer out = new OutputStreamWriter(fos, "UTF8");
			out.write(str);
			out.close();
			ByteArrayInputStream fis = new ByteArrayInputStream(fos.toByteArray());

			InputStreamReader isr = new InputStreamReader(fis, "UTF8");
			Reader in = new BufferedReader(isr);
			int ch;

			while ((ch = in.read()) > -1) {
				buffer.append((char) ch);
			}

			in.close();

			return buffer.toString();
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Another implementation native2ascii by create temp file.
	 * 
	 * @param str
	 *            native string.
	 * @return ascii string.
	 */
	public static String ascii2NativeByTempFile(String str) {
		StringBuffer buffer = new StringBuffer();

		try {
			File file = File.createTempFile("fjcy", "tmp");
			FileOutputStream fos = new FileOutputStream(file);
			Writer out = new OutputStreamWriter(fos, "UTF8");
			out.write(str);
			out.close();
			FileInputStream fis = new FileInputStream(file);
			InputStreamReader isr = new InputStreamReader(fis, "UTF8");
			Reader in = new BufferedReader(isr);
			int ch;
			while ((ch = in.read()) > -1) {
				buffer.append((char) ch);
			}
			in.close();
			return buffer.toString();
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Ascii to native string. It's same as execut native2ascii.exe -reverse.
	 * 
	 * @param str
	 *            ascii string.
	 * @return native string.
	 */
	public static String native2Ascii(String str) {
		String output = "";

		char[] ca = str.toCharArray();
		int x;

		for (x = 0; x < ca.length; ++x) {
			char a = ca[x];
			if (a > 255) {
				output += "\\u" + Integer.toHexString(a);
			} else {
				output += a;
			}
		}

		return output;
	}
}
